/*
 * Copyright (c) 2023 fred
 * Licensed under the Apache License,Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
import { Validate } from '../helper/Validate';
import { StringUtil } from '../internal/StringUtil';
import constants from '../util/Constants';
import { OutputSettings } from './OutputSettings';
import { LeafNode } from './LeafNode';
import { Syntax } from './Syntax';

export class DocumentType extends LeafNode {
  private static _NAME = "name"
  private static _PUB_SYS_KEY = "pubSysKey"
  private static _PUBLIC_ID = "publicId"
  private static _SYSTEM_ID = "systemId"
  // todo: quirk mode from publicId and systemId
  /**
   * Create a new doctype element.
   * @param name the doctype's name
   * @param publicId the doctype's public ID
   * @param systemId the doctype's system ID
   */
  constructor(name: string, publicId: string, systemId: string) {
    super()
    Validate.notNull(name)
    Validate.notNull(publicId)
    Validate.notNull(systemId)
    this.setAttr(DocumentType._NAME, name)
    this.setAttr(DocumentType._PUBLIC_ID, publicId)
    this.setAttr(DocumentType._SYSTEM_ID, systemId)
    this.updatePubSyskey()
  }

  public setPubSysKey(value: string) {
    if (value !== undefined && value !== null) {
      this.setAttr(DocumentType._PUB_SYS_KEY, value)
    }
  }

  private updatePubSyskey() {
    if (this.has(DocumentType._PUBLIC_ID)) {
      this.setAttr(DocumentType._PUB_SYS_KEY, constants.PUBLIC_KEY)
    } else if (this.has(DocumentType._SYSTEM_ID)) {
      this.setAttr(DocumentType._PUB_SYS_KEY, constants.SYSTEM_KEY)
    }
  }

  /**
   * Get this doctype's name (when set, or empty string)
   * @return doctype name
   */
  public getName(): string {
    return this.getAttr(DocumentType._NAME)
  }

  /**
   * Get this doctype's Public ID (when set, or empty string)
   * @return doctype Public ID
   */
  public getPublicId(): string {
    return this.getAttr(DocumentType._PUBLIC_ID)
  }

  /**
   * Get this doctype's System ID (when set, or empty string)
   * @return doctype System ID
   */
  public getSystemId(): string {
    return this.getAttr(DocumentType._SYSTEM_ID)
  }

  public nodeName(): string {
    return "#doctype"
  }

  outerHtmlHead(accum: string[], depth: number, out: OutputSettings) {
    // add a newline if the doctype has a preceding node (which must be a comment)
    if (this.siblingIndex > 0 && out.getPrettyPrint()) {
      accum.push('\n');
    }

    if (out.getSyntax() === Syntax.html && !this.has(DocumentType._PUBLIC_ID) && !this.has(DocumentType._SYSTEM_ID)) {
      // looks like a html5 doctype, go lowercase for aesthetics
      accum.push("<!doctype");
    } else {
      accum.push("<!DOCTYPE");
    }
    if (this.has(DocumentType._NAME)) {
      accum.push(" ")
      accum.push(this.getAttr(DocumentType._NAME));
    }
    if (this.has(DocumentType._PUB_SYS_KEY)) {
      accum.push(" ")
      accum.push(this.getAttr(DocumentType._PUB_SYS_KEY));
    }
    if (this.has(DocumentType._PUBLIC_ID)) {
      accum.push(" \"")
      accum.push(this.getAttr(DocumentType._PUBLIC_ID))
      accum.push('"');
    }
    if (this.has(DocumentType._SYSTEM_ID)) {
      accum.push(" \"")
      accum.push(this.getAttr(DocumentType._SYSTEM_ID))
      accum.push('"');
      accum.push('>');
    }

  }

  outerHtmlTail(accum: string[], depth: number, out: OutputSettings) {
  }

  private has(attribute: string): boolean {
    return !StringUtil.isBlank(this.getAttr(attribute))
  }
}

